package middleware

import (
	"bytes"
	"fmt"
	"github.com/google/uuid"

	"io"

	"net/http"

	"net/url"

	"strings"

	"time"

	"gitee.com/goddesszz/gocommon/myutil"

	"github.com/gin-gonic/gin"
)

func AccessView(ctx *gin.Context) {
	var uri = ctx.Request.RequestURI

	var info = fmt.Sprintf("===================> 访问页面 %s ", uri)
	fmt.Println(info)

	ctx.Next() //放行，执行下去

}

// 监控访问接口的请求参数、响应数据 及 消耗时间
func AccessMonitor(ctx *gin.Context) {
	var uri = ctx.Request.RequestURI
	var headers = ctx.Request.Header
	// 获取处理函数名
	var handlerName = ctx.HandlerName()

	ctx.Request.ParseForm() //先要解析form

	// var params = ctx.Request.URL.Query()
	// fmt.Println("[minitor] -> "+"query params = ", params) //ok
	//
	// var postForm = ctx.Request.PostForm
	// fmt.Println("[minitor] -> "+"form params = ", postForm) //ok

	var form = ctx.Request.Form //相当于 form + query合并为Form

	// 接收 body JSON
	var bodyJson = readBody(ctx.Request)
	// fmt.Println("[minitor] -> "+"body params = ", bodyJson)

	// 生成请求唯一ID
	aid, _ := uuid.NewRandom()
	ctx.Set("aid", aid) //存储到gin上下文

	var info = fmt.Sprintf("===================> [aid: %s] 接口访问信息 %s ↲\n", aid, handlerName) +
		fmt.Sprintf("[请求URI] %s \n", uri) +
		fmt.Sprintf("[请求Headers (x-)]%s \n", printXHeaders(headers)) +
		fmt.Sprintf("[请求参数] %s ", printForm(form)+bodyJson)
	fmt.Println(info)

	startTime := time.Now().UnixMilli()

	ctx.Next() //放行，执行下去

	endTime := time.Now().UnixMilli()

	var endInfo = fmt.Sprintf("<=================== [aid: %s] 接口访问耗时 %s cost %d(ms) ", aid, handlerName, int(endTime-startTime))
	fmt.Println(endInfo)
}

func readBody(request *http.Request) string {
	var bodyJson string

	// 只处理Content-Type为JSON的请求
	contentType := request.Header.Get("Content-Type")
	if strings.HasPrefix(contentType, "application/json") {
		// 读取原始请求体
		bodyBytes, err := io.ReadAll(request.Body)

		if err == nil {
			request.Body = io.NopCloser(bytes.NewBuffer(bodyBytes)) // 重新包装请求体，让后续处理能正常读取
			bodyJson = string(bodyBytes)
		}
	}
	return bodyJson
}

// printHeaders 将headers映射转换为格式化的字符串
func printXHeaders(headers http.Header) string {
	var buf bytes.Buffer // 相当于Java的StringBuilder

	for k, v := range headers {
		if strings.HasPrefix(strings.ToLower(k), "x-") {
			fmt.Fprintf(&buf, "\n\t%-20s : %s", k, strings.Join(v, ","))
		}
	}
	return buf.String()
}

func printForm(form url.Values) string {
	if len(form) > 0 {
		return myutil.JsonToString(form)
	} else {
		return ""
	}
}
